Repository navigation
Conversation
…ents from the call The pin goes from >=0.8.0,<0.9.0 to >=1.23.1,<2.0.0. Grammars that 0.8 does not ship (Lean, among others) are only in 1.x. The 1.x Dart grammar parses `Foo<T>(x)` as an identifier with a call selector whose argument_part holds the type_arguments, not as a relational expression. `_handle_generic_invocation` never saw it, so the type-argument edges (`Garage.open -> Item`, `carProvider -> Car`) were lost. `_process_chain` now takes them from the call. The relational expression path stays for grammars that still misparse it. 1.x downloads each grammar on first use and caches it. The Docker image fetches the grammars the analyzers load at build time, so it runs offline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… cannot be downloaded tree-sitter-language-pack 1.x downloads each grammar on first use. Without network access the first load raises a DownloadError that names a URL but not the cause or the fix, and the per-file except blocks of the analyzers swallow it, so the language drops out of the graph with a traceback per file. `utils/grammars.py` loads pack grammars through `get_pack_parser`, which turns the DownloadError into a GrammarUnavailableError that names the grammar, the cache folder and the `t.download([...])` command. `analyze_code_files` calls `ensure_pack_grammars` before the first file, so the run stops once. `PACK_GRAMMARS_BY_LANGUAGE` lists the grammars each language loads, and a test checks that docker/Dockerfile downloads the same set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…esolution The tree-sitter Lean grammar fails on many commands and notations and gives `end` as a flat node, so the analyzer uses two layers. A header scanner reads declarations, the namespace/section/mutual stack, `open` (also `open X in`), imports, spans and docstrings from the source with comments and strings masked. References come from the tree-sitter identifiers in each declaration, also inside ERROR nodes, without binders, let/have/fun/intro names and match patterns. CallGraphAnalyzer resolves a Lean reference only to an exact fully qualified name, in Lean's order: the declaration's namespaces, the root, then the open namespaces, in the caller's file and the files it imports transitively. Private names stay in their file. No match, or more than one, drops the reference, and a `lean` branch keeps this authoritative like Go and Dart. Constructor and field names link to their structure or inductive, and a dotted name falls back to its longest matching prefix (`origin.x`). Lean is registered with the file discovery, the CLI validators and the MCP tools. `.lake/` and `lake-packages/` are skipped, lakefile.lean/.toml are build artifacts, and lake-manifest.json and lean-toolchain are manifests. The Docker image downloads the `lean` grammar. Refs FSoft-AI4Code#154 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Lean 4 analyzer, with the two-layer design agreed in #154.
Stacked on #156. This PR targets
main, because GitHub cannot use afork branch as the base. Its first two commits are #156. Review only the
last two commits,
feat: Lean 4 analyzer, ...and aformat fix of its test. I will rebase this PR when #156
is merged.
Design
are masked with spaces of the same UTF-8 length, so lines and byte offsets
do not move. The scanner then reads the Lean commands line by line:
def,theorem/lemma,abbrev,instance,structure,class,class inductive,inductive,axiomandopaque, with attributes and modifiersnamespace/section/mutual/endstack, andopen, alsoopen X inimport, spans, and/-- -/docstringsIt does not use the parse tree, so an
ERRORregion does not hide adeclaration.
identifiernode in the lines of a declaration, also the nodes inside
ERRORnodes.Text that an
ERRORnode does not cover with child nodes is tokenizedfrom the masked source. Local names are removed: binders,
let,have,fun,intro/obtain, match patterns, and a dotted name whose firstpart is local (
p.x).Resolution is in
CallGraphAnalyzer, as for Go and Dart:are, in Lean's order:
visible. An import maps to a file by its path suffix (
Geo.Pointtosrc/Geo/Point.lean), because the Lake source folder is not known. Aprivatename is visible only in its own file.leanbranch in_resolve_calleeand_has_authoritative_resolutionstops the name-onlyfallback.
Point.mk,Point.x,Shape.dot) link totheir structure or inductive. When a whole dotted name matches nothing,
its longest prefix that matches is the constant, and the rest are
projections (
origin.xlinks toorigin).Other parts:
structureisstruct,classisinterface,inductiveisclass, and the rest arefunction.node_typekeeps thekeyword (
lemmabecomestheorem).instanceis namedinstance_L<line>..lake/andlake-packages/are skipped.lakefile.leanandlakefile.tomlare build artifacts, andlake-manifest.jsonandlean-toolchainare manifests.tools and the graph viewer (
lang-lean). The Docker image downloads theleangrammar. The grammar test of deps: move tree-sitter-language-pack to 1.x, with a clear error when a grammar cannot be downloaded #156 checks the Dockerfile list.Known limits
These are the limits from #154, plus three that I found during the work:
v.normforVec.norm) needs typeinformation, so it does not resolve.
notation/macroare lost.the next command at the same or a smaller indentation.
that has the same simple name as a local of that declaration is not linked.
matches in the open namespaces drop the reference.
Measurement
I ran it on a private corpus of 1,066 Lean 4 files (programs and proofs, not
Mathlib), and I checked 300 sampled files:
checked were all in those regions, not real declarations.
is small next to the LLM phase of a run.
Tests
tests/test_lean_analyzer.py(new, 21 tests, synthetic Lean only):open X in, imported and alias edgesERRORregionsprivateand not-imported names_root_andmutualtests/test_artifact_analyzer.pyhas rows for the Lake files.test_doc_write_guard.py::test_warning_reports_rejected_tool_callsalsofails on
main, as noted in deps: move tree-sitter-language-pack to 1.x, with a clear error when a grammar cannot be downloaded #156.ruff checkandruff format --checkpass.Note:
tests/test_lean_analyzer.pyis added withgit add -f, because oftests/*in.gitignore.Closes #154
🤖 Generated with Claude Code